﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using MDSAdministration;

namespace MDSAdministration
{
    public class BusinessHelper
    {

        public static CompareModel getServerDirectionModel(ServerDirection sd, CompareModel modelA, CompareModel modelB)
        {
            if (sd == ServerDirection.ServerB)
            {
                return modelB;
            }

            if (sd == ServerDirection.ServerA)
            {
                return modelA;
            }

            return null;
        }

        public static string BuildExecuteProcessString(bool? Validate, string Region)
        {
            string validateValue = "0";
            if (Validate.HasValue && Validate.Value == true)
            {
                validateValue = "1";
            }

            return "EXEC dbo.ExtractProcess @region_code = '" + Region + "', @Validate = " + validateValue;
            
        }

        public static void buildModel(DataSet ds, CompareModel m)
        {
            m.Entities.Clear();
            m.Views.Clear();

            if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
            {
                string currszModel = "";
                string currszEntity = "";
                CompareEntity currEntity = null;

                var containsStaging = ds.Tables[0].Columns.Contains(Constants.ENTITY_STAGINGBASE);

                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    if (currszModel != DataHelper.dataCellStringConv(dr, Constants.MODEL_NAME))
                    {
                        currszModel = DataHelper.dataCellStringConv(dr, Constants.MODEL_NAME);
                        m.Name = DataHelper.dataCellStringConv(dr, Constants.MODEL_NAME);
                        m.IsSystem = DataHelper.dataCellBoolConv(dr, Constants.MODEL_ISSYSTEM);
                        m.ModelID = DataHelper.dataCellIntConv(dr, Constants.MODEL_ID);
                    }
                    if (currszEntity != DataHelper.dataCellStringConv(dr, Constants.ENTITY_NAME))
                    {
                        currszEntity = DataHelper.dataCellStringConv(dr, Constants.ENTITY_NAME);
                        currEntity = new CompareEntity();
                        currEntity.Name = DataHelper.dataCellStringConv(dr, Constants.ENTITY_NAME);
                        currEntity.EntityMUID = DataHelper.dataCellStringConv(dr, Constants.ENTITY_MUID);
                        currEntity.EntityID = DataHelper.dataCellIntConv(dr, Constants.ENTITY_ID);
                        currEntity.IsSystem = DataHelper.dataCellBoolConv(dr, Constants.ENTITY_ISSYSTEM);
                        currEntity.EntityTable = DataHelper.dataCellStringConv(dr, Constants.ENTITY_ENTITYTABLE);
                        currEntity.SecurityTable = DataHelper.dataCellStringConv(dr, Constants.ENTITY_SECURITYTABLE);
                        currEntity.HierarchyTable = DataHelper.dataCellStringConv(dr, Constants.ENTITY_HIERARCHYTABLE);
                        currEntity.HierarchyParentTable = DataHelper.dataCellStringConv(dr, Constants.ENTITY_HIERARCHYPARENTTABLE);
                        currEntity.CollectionTable = DataHelper.dataCellStringConv(dr, Constants.ENTITY_COLLECTIONTABLE);
                        currEntity.CollectionMemberTable = DataHelper.dataCellStringConv(dr, Constants.ENTITY_COLLECTIONMEMBERTABLE);
                        currEntity.Model = m;
                        if (containsStaging)
                        {
                            currEntity.StagingBase = DataHelper.dataCellStringConv(dr, Constants.ENTITY_STAGINGBASE);
                            currEntity.CodeGenSeed = (dr[Constants.ENTITY_CODEGENSEED] == DBNull.Value) ? 0 : 1;
                        }
                        currEntity.IsBase = DataHelper.dataCellBoolConv(dr, Constants.ENTITY_ISBASE);
                        currEntity.IsFlat = DataHelper.dataCellBoolConv(dr, Constants.ENTITY_ISFLAT);

                        m.Entities.Add(CompareEntity.getEntityKey(currEntity.Name), currEntity);

                    }
                    var currAttribute = new CompareAttribute();

                    currAttribute.Name = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTE_NAME);
                    currAttribute.IsSystem = DataHelper.dataCellBoolConv(dr, Constants.ATTRIBUTE_ISSYSTEM);
                    currAttribute.SortOrder = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_SORTORDER);
                    currAttribute.MemberType = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_MEMBERTYPEID);
                    currAttribute.MUID = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTE_MUID);
                    currAttribute.DisplayName = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTE_DISPLAYNAME);
                    currAttribute.TableColumn = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTE_TABLECOLUMN);
                    currAttribute.AttributeTypeID = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_ATTRIBUTETYPEID);
                    currAttribute.DataTypeID = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_DATATYPEID);
                    currAttribute.DataTypeInformation = DataHelper.dataCellNullableIntConv(dr, Constants.ATTRIBUTE_DATATYPEINFORMATION);
                    currAttribute.InputMaskID = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_INPUTMASKID);
                    currAttribute.DisplayWidth = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_DISPLAYWIDTH);

                    if (dr[Constants.ATTRIBUTE_DOMAINENTITYID].GetType().FullName == "System.DBNull")
                    {
                        currAttribute.DomainEntityID = null;
                        currAttribute.DomainEntityName = "DEFAULT";
                        currAttribute.DomainEntityMUID = "00000000-0000-0000-0000-000000000000";
                    }
                    else
                    {
                        currAttribute.DomainEntityID = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_DOMAINENTITYID);
                        currAttribute.DomainEntityName = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTE_DOMAINENTITYNAME);
                        currAttribute.DomainEntityMUID = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTE_DOMAINENTITYMUID);
                    }

                    currAttribute.ChangeTrackingGroup = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTE_CHANGETRACKINGGROUP);
                    currAttribute.IsCode = DataHelper.dataCellBoolConv(dr, Constants.ATTRIBUTE_ISCODE);
                    currAttribute.IsName = DataHelper.dataCellBoolConv(dr, Constants.ATTRIBUTE_ISNAME);
                    currAttribute.IsReadOnly = DataHelper.dataCellBoolConv(dr, Constants.ATTRIBUTE_ISREADONLY);

                    currAttribute.AttributeValidationID = DataHelper.dataCellNullableIntConv(dr, Constants.ATTRIBUTE_ATTRIBUTEVALIDATIONID);

                    currAttribute.IsRequired = DataHelper.dataCellBoolConv(dr, Constants.ATTRIBUTE_ISREQUIRED);
                    currAttribute.Entity = currEntity;

                    currEntity.Attributes.Add(CompareAttribute.getAttributeKey(currAttribute.Name, currAttribute.MemberType), currAttribute);
                }

                buildView(ds, m);
                buildAttributeGroup(ds, m);
            }
        }
        public static void buildAttributeGroup(DataSet ds, MDSAdministration.CompareModel m)
        {
            if (ds.Tables.Count > 2)
            {
                foreach (DataRow dr in ds.Tables[2].Rows)
                {

                    var entity = m.Entities[CompareEntity.getEntityKey(DataHelper.dataCellStringConv(dr, Constants.ENTITY_NAME))];

                    CompareAttributeGroup ag = null;

                    if (entity.AttributeGroups.ContainsKey(CompareAttributeGroup.getAttributeGroupKey(DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTEGROUP_NAME))))
                    {
                        ag = entity.AttributeGroups[CompareAttributeGroup.getAttributeGroupKey(DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTEGROUP_NAME))];
                    }
                    else
                    {
                        ag = new CompareAttributeGroup();
                        ag.Entity = entity;
                        ag.MUID = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTEGROUP_MUID);
                        ag.Name = DataHelper.dataCellStringConv(dr, Constants.ATTRIBUTEGROUP_NAME);
                        ag.SortOrder = DataHelper.dataCellIntConv(dr, Constants.ATTRIBUTEGROUP_SORTORDER);
                        entity.AttributeGroups.Add(CompareAttributeGroup.getAttributeGroupKey(ag.Name), ag);
                    }

                    if (ds.Tables.Count > 3)
                    {
                        var result = (from r in ds.Tables[3].AsEnumerable()
                                      where r.Field<string>("AttributeGroup_MUID") == ag.MUID
                                      select r);

                        foreach (var drAGD in result)
                        {

                            CompareAttributeGroupDetail agd = null;
                            if (
                                ag.AttributeGroupDetails.ContainsKey(
                                    CompareAttribute.getAttributeKey(
                                        DataHelper.dataCellStringConv(drAGD, Constants.ATTRIBUTE_NAME),
                                        DataHelper.dataCellIntConv(drAGD, Constants.ATTRIBUTE_MEMBERTYPEID))))
                            {
                                agd = ag.AttributeGroupDetails[
                                    CompareAttribute.getAttributeKey(
                                        DataHelper.dataCellStringConv(drAGD, Constants.ATTRIBUTE_NAME),
                                        DataHelper.dataCellIntConv(drAGD, Constants.ATTRIBUTE_MEMBERTYPEID))];
                            }
                            else
                            {
                                agd = new CompareAttributeGroupDetail();
                                agd.Attribute = entity.Attributes[CompareAttribute.getAttributeKey(
                                    DataHelper.dataCellStringConv(drAGD, Constants.ATTRIBUTE_NAME),
                                    DataHelper.dataCellIntConv(drAGD, Constants.ATTRIBUTE_MEMBERTYPEID))];
                                agd.AttributeGroup = ag;
                                agd.MUID = DataHelper.dataCellStringConv(drAGD, Constants.ATTRIBUTEGROUPDETAIL_MUID);
                                agd.SortOrder = DataHelper.dataCellIntConv(drAGD, Constants.ATTRIBUTEGROUPDETAIL_SORTORDER);
                                agd.AttributeID = DataHelper.dataCellIntConv(drAGD, Constants.ATTRIBUTE_ID);
                                ag.AttributeGroupDetails.Add(
                                    CompareAttributeGroupDetail.getAttributeGroupDetailKey(ag, agd.Attribute), agd);
                            }
                        }
                    }
                }
            }
            else
            {
                throw new System.Exception("Attribute Group DataSet is missing");
            }
        }
        private static void buildView(DataSet ds, CompareModel m)
        {
            if (ds.Tables.Count > 1)
            {
                foreach (DataRow dr in ds.Tables[1].Rows)
                {
                    var cv = new CompareView();
                    cv.DerivedHierarchyID = DataHelper.dataCellNullableIntConv(dr, Constants.VIEW_DERIVEDHIERARCHYID);
                    cv.IsDirty = DataHelper.dataCellBoolConv(dr, Constants.VIEW_ISDIRTY);
                    cv.Levels = DataHelper.dataCellNullableIntConv(dr, Constants.VIEW_LEVELS);
                    cv.Name = DataHelper.dataCellStringConv(dr, Constants.VIEW_NAME);
                    cv.ViewFormatID = DataHelper.dataCellNullableIntConv(dr, Constants.VIEW_VIEWFORMATID);
                    cv.EntityName = DataHelper.dataCellStringConv(dr, Constants.ENTITY_NAME);
                    cv.EntityMUID = DataHelper.dataCellStringConv(dr, Constants.ENTITY_MUID);
                    cv.PhysicallyExists = DataHelper.dataCellBoolConv(dr, Constants.VIEW_PHYSICALLYEXISTS);

                    if (!m.Views.ContainsKey(CompareView.getViewKey(cv.Name)))
                    {
                        m.Views.Add(CompareView.getViewKey(cv.Name), cv);
                    }
                }
            }
            else
            {
                throw new System.Exception("View DataSet is missing");
            }
        }

        public static Dictionary<string, ComparedObject> CompareModels(CompareModel modelA, CompareModel modelB, CheckStates cStates, ServerMDSDetails ServerA, ServerMDSDetails ServerB)
        {
            var c = new Dictionary<string, ComparedObject>();

            foreach (var entityA in modelA.Entities)
            {
                if (modelB.Entities.ContainsKey(entityA.Key))
                {
                    var entityB = modelB.Entities[entityA.Key];

                    ObjectStatus entityCompareStatus = entityCompare(entityA.Value, entityB, cStates);

                    if (entityCompareStatus == ObjectStatus.Same)
                    {
                        foreach (var attributeA in entityA.Value.Attributes)
                        {
                            if (entityB.Attributes.ContainsKey(attributeA.Key))
                            {
                                var attributeB = entityB.Attributes[attributeA.Key];

                                if (attributeCompare(attributeA.Value, attributeB, cStates) != ObjectStatus.Same)
                                {
                                    entityCompareStatus = ObjectStatus.Different;
                                    break;
                                }
                            }
                            else
                            {
                                entityCompareStatus = ObjectStatus.Different;
                                break;
                            }
                        }
                        if (entityCompareStatus == ObjectStatus.Same)
                        {
                            foreach (var attributeB in modelB.Entities[entityA.Key].Attributes)
                            {
                                if (entityA.Value.Attributes.ContainsKey(attributeB.Key))
                                {
                                    if (attributeCompare(entityA.Value.Attributes[attributeB.Key], attributeB.Value, cStates) != ObjectStatus.Same)
                                    {
                                        entityCompareStatus = ObjectStatus.Different;
                                        break;
                                    }
                                }
                                else
                                {
                                    entityCompareStatus = ObjectStatus.Different;
                                    break;
                                }
                            }
                        }
                        //Check AttributeGroup A against B
                        if (entityCompareStatus == ObjectStatus.Same)
                        {
                            foreach (var attributeGroupA in entityA.Value.AttributeGroups)
                            {
                                if (entityB.AttributeGroups.ContainsKey(attributeGroupA.Key))
                                {
                                    var attributeGroupB = entityB.AttributeGroups[attributeGroupA.Key];

                                    if (attributeGroupCompare(attributeGroupA.Value, attributeGroupB, cStates) != ObjectStatus.Same)
                                    {
                                        entityCompareStatus = ObjectStatus.Different;
                                        break;
                                    }
                                    else
                                    {
                                        foreach (var attributeGroupDetailA in attributeGroupA.Value.AttributeGroupDetails)
                                        {
                                            if (attributeGroupB.AttributeGroupDetails.ContainsKey(attributeGroupDetailA.Key))
                                            {
                                                var attributeGroupDetailB = attributeGroupB.AttributeGroupDetails[attributeGroupDetailA.Key];
                                                if (attributeGroupDetailCompare(attributeGroupDetailA.Value, attributeGroupDetailB, cStates) != ObjectStatus.Same)
                                                {
                                                    entityCompareStatus = ObjectStatus.Different;
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                entityCompareStatus = ObjectStatus.Different;
                                                break;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    entityCompareStatus = ObjectStatus.Different;
                                    break;
                                }
                            }
                        }


                        //Check AttributeGroup B against A
                        if (entityCompareStatus == ObjectStatus.Same)
                        {
                            foreach (var attributeGroupB in modelB.Entities[entityA.Key].AttributeGroups)
                            {
                                if (entityA.Value.AttributeGroups.ContainsKey(attributeGroupB.Key))
                                {
                                    var attributeGroupA = entityA.Value.AttributeGroups[attributeGroupB.Key];
                                    if (attributeGroupCompare(attributeGroupA, attributeGroupB.Value, cStates) != ObjectStatus.Same)
                                    {
                                        entityCompareStatus = ObjectStatus.Different;
                                        break;
                                    }
                                    else
                                    {
                                        foreach (var attributeGroupDetailB in attributeGroupB.Value.AttributeGroupDetails)
                                        {
                                            if (attributeGroupA.AttributeGroupDetails.ContainsKey(attributeGroupDetailB.Key))
                                            {
                                                var attributeGroupDetailA = attributeGroupA.AttributeGroupDetails[attributeGroupDetailB.Key];
                                                if (attributeGroupDetailCompare(attributeGroupDetailA, attributeGroupDetailB.Value, cStates) != ObjectStatus.Same)
                                                {
                                                    entityCompareStatus = ObjectStatus.Different;
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                entityCompareStatus = ObjectStatus.Different;
                                                break;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    entityCompareStatus = ObjectStatus.Different;
                                    break;
                                }
                            }
                        }
                    }

                    c.Add(entityA.Key, new ComparedObject() { Location = entityCompareStatus.ToString(), ObjectName = entityA.Value.Name, ObjectType = Constants.OBJECT_TYPE_ENTITY, locationType = entityCompareStatus });

                }
                else //Check for rename
                {
                    foreach (var entityB in modelB.Entities)
                    {
                        if (entityA.Value.EntityMUID == entityB.Value.EntityMUID)
                        {
                            c.Add(entityA.Key, new ComparedObject() { Location = ObjectStatus.Rename.ToString(), ObjectName = entityA.Value.Name, ObjectType = Constants.OBJECT_TYPE_ENTITY, locationType = ObjectStatus.Rename });
                        }
                    }
                }

                if (!(c.ContainsKey(entityA.Key)))
                {
                    c.Add(entityA.Key, new ComparedObject() { Location = String.Format("Exists only on {0}|{1}|{2}|{3}", ServerA.ServerName, ServerA.Database, ServerA.Model, ServerA.ModelVersion), ObjectName = entityA.Value.Name, ObjectType = Constants.OBJECT_TYPE_ENTITY, locationType = ObjectStatus.ServerA });
                }


            }

            foreach (var entityB in modelB.Entities)
            {
                if (!(modelA.Entities.ContainsKey(entityB.Key)))
                {
                    bool IsEntityRenamed = false;
                    foreach (var entityA in modelA.Entities)
                    {
                        if (entityA.Value.EntityMUID == entityB.Value.EntityMUID)
                        {
                            if (!(c.ContainsKey(entityA.Key)))
                            {
                                //This code should not be called, should be handled above.
                                c.Add(entityA.Key, new ComparedObject() { Location = ObjectStatus.Rename.ToString(), ObjectName = entityA.Value.Name, ObjectType = Constants.OBJECT_TYPE_ENTITY, locationType = ObjectStatus.Rename });
                            }
                            IsEntityRenamed = true;
                            break;
                        }
                    }
                    if (!IsEntityRenamed)
                    {
                        c.Add(entityB.Key, new ComparedObject() { Location = String.Format("Exists only on {0}|{1}|{2}|{3}", ServerB.ServerName, ServerB.Database, ServerB.Model, ServerB.ModelVersion), ObjectName = entityB.Value.Name, ObjectType = Constants.OBJECT_TYPE_ENTITY, locationType = ObjectStatus.ServerB });
                    }
                }
            }

            foreach (var viewA in modelA.Views)
            {
                if (modelB.Views.ContainsKey(viewA.Key))
                {
                    ObjectStatus viewCompareStatus = viewCompare(viewA.Value, modelB.Views[viewA.Key], cStates);
                    c.Add(viewA.Key, new ComparedObject() { Location = viewCompareStatus.ToString(), ObjectName = viewA.Value.Name, ObjectType = Constants.OBJECT_TYPE_VIEW, locationType = viewCompareStatus });
                }
                else
                {
                    foreach (var viewB in modelB.Views)
                    {
                        if (viewA.Value.EntityMUID == viewB.Value.EntityMUID)
                        {
                            c.Add(viewA.Key, new ComparedObject() { Location = ObjectStatus.Rename.ToString(), ObjectName = viewA.Value.Name, ObjectType = Constants.OBJECT_TYPE_VIEW, locationType = ObjectStatus.Rename });
                            break;
                        }
                    }
                    if (!(c.ContainsKey(viewA.Key)))
                    {
                        c.Add(viewA.Key, new ComparedObject() { Location = String.Format("Exists only on {0}|{1}|{2}|{3}", ServerA.ServerName, ServerA.Database, ServerA.Model, ServerA.ModelVersion), ObjectName = viewA.Value.Name, ObjectType = "View", locationType = ObjectStatus.ServerA });
                    }
                }
            }

            foreach (var viewB in modelB.Views)
            {
                if (!(modelA.Views.ContainsKey(viewB.Key)))
                {
                    bool IsViewRenamed = false;
                    foreach (var viewA in modelA.Views)
                    {
                        if (viewA.Value.EntityMUID == viewB.Value.EntityMUID)
                        {
                            if (!(c.ContainsKey(viewA.Key)))
                            {
                                //This code should not be called, should be handled above.
                                c.Add(viewA.Key, new ComparedObject() { Location = ObjectStatus.Rename.ToString(), ObjectName = viewA.Value.Name, ObjectType = Constants.OBJECT_TYPE_ENTITY, locationType = ObjectStatus.Rename });
                            }
                            IsViewRenamed = true;
                            break;
                        }
                    }
                    if (!IsViewRenamed)
                    {
                        c.Add(viewB.Key, new ComparedObject() { Location = String.Format("Exists only on {0}|{1}|{2}|{3}", ServerB.ServerName, ServerB.Database, ServerB.Model, ServerB.ModelVersion), ObjectName = viewB.Value.Name, ObjectType = "View", locationType = ObjectStatus.ServerB });
                    }
                }
            }
            return c;
        }
        public static ObjectStatus viewCompare(CompareView a, CompareView b, CheckStates cStates)
        {
            ObjectStatus oStatus = ObjectStatus.Same;

            if (a.Name == b.Name &&
                   a.IsDirty == b.IsDirty &&
                   a.DerivedHierarchyID == b.DerivedHierarchyID &&
                   a.Levels == b.Levels &&
                   a.ViewFormatID == b.ViewFormatID &&
                   a.PhysicallyExists == b.PhysicallyExists &&
                   a.EntityName == b.EntityName &&
                (cStates.EntityMUID ? true : (a.EntityMUID == b.EntityMUID))
                )
            {
                oStatus = ObjectStatus.Same;
            }
            else
            {
                oStatus = ObjectStatus.Different;
            }

            if (oStatus == ObjectStatus.Different)
            {
                if (a.Name == b.Name &&
                  a.IsDirty == b.IsDirty &&
                  a.DerivedHierarchyID == b.DerivedHierarchyID &&
                  a.Levels == b.Levels &&
                  a.ViewFormatID == b.ViewFormatID &&
                  a.PhysicallyExists == b.PhysicallyExists &&
               (cStates.EntityMUID ? true : (a.EntityMUID == b.EntityMUID))
               )
                {
                    oStatus = ObjectStatus.Rename;
                }
            }
            return oStatus;
        }

        public static void buildModelSytem(CompareModel m, DataSet ds, ServerMDSDetails server)
        {
            m.System = new CompareSystem
            {
                Name = ds.Tables[0].Rows[0][Constants.SYSTEM_PRODUCTNAME].ToString(),
                RegistrationKey = ds.Tables[0].Rows[0][Constants.SYSTEM_PRODUCTREGISTRATIONKEY].ToString(),
                SchemaVersion = ds.Tables[0].Rows[0][Constants.SYSTEM_SCHEMAVERSION].ToString(),
                Version = ds.Tables[0].Rows[0][Constants.SYSTEM_PRODUCTVERSION].ToString()
            };

            server.schemaVersion = m.System;
        }

        public static ObjectStatus entityCompare(CompareEntity a, CompareEntity b, CheckStates cStates)
        {
            ObjectStatus oStatus = ObjectStatus.Same;

            if (a.Name == b.Name &&
                (cStates.EntityMUID ? true : (a.EntityMUID == b.EntityMUID)) &&
                (cStates.EntityID ? true : (a.EntityID == b.EntityID)) &&
                (cStates.EntityTable ? true : (a.EntityTable == b.EntityTable)) &&
                a.IsSystem == b.IsSystem &&
                (cStates.SecurityTable ? true : (a.SecurityTable == b.SecurityTable)) &&
                a.HierarchyTable == b.HierarchyTable &&
                a.HierarchyParentTable == b.HierarchyParentTable &&
                a.CollectionTable == b.CollectionTable &&
                a.CollectionMemberTable == b.CollectionMemberTable &&
                (cStates.StagingTable ? true : (a.StagingBase == b.StagingBase)) &&
                a.IsBase == b.IsBase &&
                a.IsFlat == b.IsFlat &&
                a.CodeGenSeed == b.CodeGenSeed)
            {
                oStatus = ObjectStatus.Same;
            }
            else
            {
                oStatus = ObjectStatus.Different;
            }

            //handle entity renames
            if (oStatus == ObjectStatus.Different)
            {
                if ((cStates.EntityMUID ? true : (a.EntityMUID == b.EntityMUID)) &&
                (cStates.EntityID ? true : (a.EntityID == b.EntityID)) &&
                (cStates.EntityTable ? true : (a.EntityTable == b.EntityTable)) &&
                a.IsSystem == b.IsSystem &&
                (cStates.SecurityTable ? true : (a.SecurityTable == b.SecurityTable)) &&
                a.HierarchyTable == b.HierarchyTable &&
                a.HierarchyParentTable == b.HierarchyParentTable &&
                a.CollectionTable == b.CollectionTable &&
                a.CollectionMemberTable == b.CollectionMemberTable &&
                (cStates.StagingTable ? true : (a.StagingBase == b.StagingBase)) &&
                a.IsBase == b.IsBase &&
                a.IsFlat == b.IsFlat &&
                a.CodeGenSeed == b.CodeGenSeed)
                {
                    oStatus = ObjectStatus.Rename;
                }
            }
            return oStatus;
        }

        public static ObjectStatus attributeGroupCompare(CompareAttributeGroup a, CompareAttributeGroup b, CheckStates cStates)
        {
            ObjectStatus oStatus = ObjectStatus.Same;

            if (a.Name == b.Name &&
                (cStates.AttributeGroupMUID ? true : (a.MUID == b.MUID)) &&
                a.SortOrder == b.SortOrder
                )
            {
                oStatus = ObjectStatus.Same;
            }
            else
            {
                oStatus = ObjectStatus.Different;
            }

            //handle attribute group renames
            if (oStatus == ObjectStatus.Different)
            {
                if ((cStates.AttributeGroupMUID ? true : (a.MUID == b.MUID)) &&
                a.SortOrder == b.SortOrder)
                {
                    oStatus = ObjectStatus.Rename;
                }
            }

            return oStatus;
        }
        public static ObjectStatus attributeGroupDetailCompare(CompareAttributeGroupDetail a, CompareAttributeGroupDetail b, CheckStates cStates)
        {
            ObjectStatus oStatus = ObjectStatus.Same;

            if (a.Attribute.Name == b.Attribute.Name &&
                (cStates.AttributeGroupMUID ? true : (a.MUID == b.MUID)) &&
                a.SortOrder == b.SortOrder)
            {
                oStatus = ObjectStatus.Same;
            }
            else
            {
                oStatus = ObjectStatus.Different;
            }

            //handle attribute group renames
            if (oStatus == ObjectStatus.Different)
            {
                if ((cStates.AttributeGroupMUID ? true : (a.MUID == b.MUID)) &&
                a.SortOrder == b.SortOrder)
                {
                    oStatus = ObjectStatus.Rename;
                }
            }
            return oStatus;
        }
        public static ObjectStatus attributeCompare(CompareAttribute a, CompareAttribute b, CheckStates cStates)
        {
            ObjectStatus oStatus = ObjectStatus.Same;
            if (a.Name == b.Name &&
                   a.SortOrder == b.SortOrder &&
                   a.MemberType == b.MemberType &&
                   a.IsSystem == b.IsSystem &&
                   (cStates.AttributeMUID ? true : (a.MUID == b.MUID)) &&
                   (cStates.AttributeEntityID ? true : (a.Entity.EntityID == b.Entity.EntityID)) &&
                   a.DisplayName == b.DisplayName &&
                   (cStates.AttributeTableColumn ? true : (a.TableColumn == b.TableColumn)) &&
                   a.AttributeTypeID == b.AttributeTypeID &&
                   a.DataTypeID == b.DataTypeID &&
                   a.DataTypeInformation == b.DataTypeInformation &&
                   a.InputMaskID == b.InputMaskID &&
                   a.DisplayWidth == b.DisplayWidth &&
                   (cStates.AttributeDomainEntityID ? true : (a.DomainEntityID == b.DomainEntityID)) &&
                   a.DomainEntityName == b.DomainEntityName &&
                   (cStates.AttributeMUID ? true : (a.DomainEntityMUID == b.DomainEntityMUID)) &&
                   a.ChangeTrackingGroup == b.ChangeTrackingGroup &&
                   a.IsCode == b.IsCode &&
                   a.IsName == b.IsName &&
                   a.IsReadOnly == b.IsReadOnly &&
                   a.AttributeValidationID == b.AttributeValidationID &&
                   a.IsRequired == b.IsRequired)
            {
                oStatus = ObjectStatus.Same;
            }
            else
            {
                oStatus = ObjectStatus.Different;
            }

            //handle attribute renames
            if (oStatus == ObjectStatus.Different)
            {
                if (a.SortOrder == b.SortOrder &&
                   a.MemberType == b.MemberType &&
                   a.IsSystem == b.IsSystem &&
                   (a.MUID == b.MUID) &&
                   (cStates.AttributeEntityID ? true : (a.Entity.EntityID == b.Entity.EntityID)) &&
                   (cStates.AttributeTableColumn ? true : (a.TableColumn == b.TableColumn)) &&
                   a.AttributeTypeID == b.AttributeTypeID &&
                   a.DataTypeID == b.DataTypeID &&
                   a.DataTypeInformation == b.DataTypeInformation &&
                   a.InputMaskID == b.InputMaskID &&
                   a.DisplayWidth == b.DisplayWidth &&
                   (cStates.AttributeDomainEntityID ? true : (a.DomainEntityID == b.DomainEntityID)) &&
                   a.DomainEntityName == b.DomainEntityName &&
                   (cStates.AttributeMUID ? true : (a.DomainEntityMUID == b.DomainEntityMUID)) &&
                   a.ChangeTrackingGroup == b.ChangeTrackingGroup &&
                   a.IsCode == b.IsCode &&
                   a.IsName == b.IsName &&
                   a.IsReadOnly == b.IsReadOnly &&
                   a.AttributeValidationID == b.AttributeValidationID &&
                   a.IsRequired == b.IsRequired)
                {
                    oStatus = ObjectStatus.Rename;
                }
            }
            return oStatus;

        }

        public static string SetMemberValue(EntityColumn selectedColumn, DataRowView drv)
        {
            return SetMemberValue(selectedColumn, drv, "");
        }

        public static string SetMemberValue(EntityColumn selectedColumn, DataRowView drv, string server)
        {
            string result = "";
            switch (selectedColumn.dataType)
            {
                case MDSDataTypes.DateTime:
                    {
                        if (drv.Row.IsNull(server + selectedColumn.Name))
                        {
                            result = null;
                        }
                        else
                        {
                            DateTime dt = new DateTime();
                            if (drv[server + selectedColumn.Name].GetType().ToString() == Constants.SYSTEM_DATETIME)
                            {
                                dt = (DateTime)drv[server + selectedColumn.Name];
                            }
                            else if (drv[server + selectedColumn.Name].GetType().ToString() == Constants.SYSTEM_STRING)
                            {
                                if (!DateTime.TryParse(drv[server + selectedColumn.Name].ToString(), out dt))
                                {
                                    throw new Exception("Invalid data trying to convert to DateTime. ColumnName:" + selectedColumn.Name + " Data trying to convert:" + drv[server + selectedColumn.Name].ToString());
                                }
                            }
                            else
                            {
                                throw new Exception("Invalid data type trying to convert to DateTime.");
                            }
                            result = dt.ToString(@"yyyy/MM/dd HH:mm:ss");
                        }
                    }
                    break;
                case MDSDataTypes.Decimal:
                case MDSDataTypes.Int32:
                case MDSDataTypes.String:
                    {
                        if (selectedColumn.isDomainEntity)
                        {
                            string columnName = "";
                            if (drv.Row.Table.Columns.Contains(server + selectedColumn.Name + "_Code"))
                            {
                                columnName = server + selectedColumn.Name + "_Code";
                            }
                            else if (drv.Row.Table.Columns.Contains(server + selectedColumn.Name))
                            {
                                columnName = server + selectedColumn.Name;
                            }

                            if (drv.Row.IsNull(columnName))
                            {
                                result = null;
                            }
                            else
                            {
                                result = drv[columnName].ToString();
                            }
                        }
                        else if (drv.Row.IsNull(server + selectedColumn.Name))
                        {
                            result = null;
                        }
                        else
                        {
                            result = drv[server + selectedColumn.Name].ToString();
                        }
                    }
                    break;
            }

            return result;
        }

        public static List<ComparedObjectResult> populateComparedView(ComparedObject co, CompareModel modelA, CompareModel modelB)
        {
            var viewA = modelA.Views[CompareView.getViewKey(co.ObjectName)];
            var viewB = modelB.Views[CompareView.getViewKey(GetRenamedView(co, modelA, modelB))];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", A = viewA.Name, B = viewB.Name });
            la.Add(new ComparedObjectResult() { Type = "EntityName", A = viewA.EntityName, B = viewB.EntityName });
            la.Add(new ComparedObjectResult() { Type = "EntityMUID", A = viewA.EntityMUID, B = viewB.EntityMUID });
            la.Add(new ComparedObjectResult() { Type = "IsDirty", A = viewA.IsDirty, B = viewB.IsDirty });
            la.Add(new ComparedObjectResult() { Type = "DerivedHierarchyID", A = viewA.DerivedHierarchyID, B = viewB.DerivedHierarchyID });
            la.Add(new ComparedObjectResult() { Type = "Levels", A = viewA.Levels, B = viewB.Levels });
            la.Add(new ComparedObjectResult() { Type = "ViewFormatID", A = viewA.ViewFormatID, B = viewB.ViewFormatID });
            la.Add(new ComparedObjectResult() { Type = "PhysicallyExists", A = viewA.PhysicallyExists, B = viewB.PhysicallyExists });
            return la;
        }

        public static List<ComparedObjectResult> populateComparedViewA(ComparedObject co, CompareModel modelA)
        {
            var viewA = modelA.Views[CompareView.getViewKey(co.ObjectName)];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", A = viewA.Name });
            la.Add(new ComparedObjectResult() { Type = "IsDirty", A = viewA.IsDirty });
            la.Add(new ComparedObjectResult() { Type = "DerivedHierarchyID", A = viewA.DerivedHierarchyID });
            la.Add(new ComparedObjectResult() { Type = "Levels", A = viewA.Levels });
            la.Add(new ComparedObjectResult() { Type = "ViewFormatID", A = viewA.ViewFormatID });
            la.Add(new ComparedObjectResult() { Type = "PhysicallyExists", A = viewA.PhysicallyExists });
            return la;
        }

        public static List<ComparedObjectResult> populateComparedViewB(ComparedObject co, CompareModel modelB)
        {
            var viewB = modelB.Views[CompareView.getViewKey(co.ObjectName)];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", B = viewB.Name });
            la.Add(new ComparedObjectResult() { Type = "IsDirty", B = viewB.IsDirty });
            la.Add(new ComparedObjectResult() { Type = "DerivedHierarchyID", B = viewB.DerivedHierarchyID });
            la.Add(new ComparedObjectResult() { Type = "Levels", B = viewB.Levels });
            la.Add(new ComparedObjectResult() { Type = "ViewFormatID", B = viewB.ViewFormatID });
            la.Add(new ComparedObjectResult() { Type = "PhysicallyExists", B = viewB.PhysicallyExists });
            return la;
        }




        #region populate Entity ComparedObject Result
        public static List<ComparedObjectResult> populateComparedEntity(ComparedObject co, CompareModel modelA, CompareModel modelB)
        {
            var entityA = modelA.Entities[CompareEntity.getEntityKey(co.ObjectName)];
            var entityB = modelB.Entities[CompareEntity.getEntityKey(GetRenamedEntity(co, modelA, modelB))];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", A = entityA.Name, B = entityB.Name });
            la.Add(new ComparedObjectResult() { Type = "EntityMUID", A = entityA.EntityMUID, B = entityB.EntityMUID });
            la.Add(new ComparedObjectResult() { Type = "EntityID", A = entityA.EntityID, B = entityB.EntityID });
            la.Add(new ComparedObjectResult() { Type = "CollectionMemberTable", A = entityA.CollectionMemberTable, B = entityB.CollectionMemberTable });
            la.Add(new ComparedObjectResult() { Type = "CollectionTable", A = entityA.CollectionTable, B = entityB.CollectionTable });
            la.Add(new ComparedObjectResult() { Type = "EntityTable", A = entityA.EntityTable, B = entityB.EntityTable });
            la.Add(new ComparedObjectResult() { Type = "HierarchyParentTable", A = entityA.HierarchyParentTable, B = entityB.HierarchyParentTable });
            la.Add(new ComparedObjectResult() { Type = "HierarchyTable", A = entityA.HierarchyTable, B = entityB.HierarchyTable });
            la.Add(new ComparedObjectResult() { Type = "IsBase", A = entityA.IsBase, B = entityB.IsBase });
            la.Add(new ComparedObjectResult() { Type = "IsFlat", A = entityA.IsFlat, B = entityB.IsFlat });
            la.Add(new ComparedObjectResult() { Type = "IsSystem", A = entityA.IsSystem, B = entityB.IsSystem });
            la.Add(new ComparedObjectResult() { Type = "SecurityTable", A = entityA.SecurityTable, B = entityB.SecurityTable });
            la.Add(new ComparedObjectResult() { Type = "StagingBase", A = entityA.StagingBase, B = entityB.StagingBase });
            la.Add(new ComparedObjectResult() { Type = "CodeGenSeed", A = entityA.CodeGenSeed, B = entityB.CodeGenSeed });

            return la;
        }

        public static List<ComparedObjectResult> populateComparedEntityB(ComparedObject co, CompareModel modelB)
        {
            var entityB = modelB.Entities[CompareEntity.getEntityKey(co.ObjectName)];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", B = entityB.Name });
            la.Add(new ComparedObjectResult() { Type = "EntityMUID", B = entityB.EntityMUID });
            la.Add(new ComparedObjectResult() { Type = "EntityID", B = entityB.EntityID });
            la.Add(new ComparedObjectResult() { Type = "CollectionMemberTable", B = entityB.CollectionMemberTable });
            la.Add(new ComparedObjectResult() { Type = "CollectionTable", B = entityB.CollectionTable });
            la.Add(new ComparedObjectResult() { Type = "EntityTable", B = entityB.EntityTable });
            la.Add(new ComparedObjectResult() { Type = "HierarchyParentTable", B = entityB.HierarchyParentTable });
            la.Add(new ComparedObjectResult() { Type = "HierarchyTable", B = entityB.HierarchyTable });
            la.Add(new ComparedObjectResult() { Type = "IsBase", B = entityB.IsBase });
            la.Add(new ComparedObjectResult() { Type = "IsFlat", B = entityB.IsFlat });
            la.Add(new ComparedObjectResult() { Type = "IsSystem", B = entityB.IsSystem });
            la.Add(new ComparedObjectResult() { Type = "SecurityTable", B = entityB.SecurityTable });
            la.Add(new ComparedObjectResult() { Type = "StagingBase", B = entityB.StagingBase });
            la.Add(new ComparedObjectResult() { Type = "CodeGenSeed", B = entityB.CodeGenSeed });

            return la;
        }

        public static List<ComparedObjectResult> populateComparedEntityA(ComparedObject co, CompareModel modelA)
        {
            var entityA = modelA.Entities[CompareEntity.getEntityKey(co.ObjectName)];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", A = entityA.Name });
            la.Add(new ComparedObjectResult() { Type = "EntityMUID", A = entityA.EntityMUID });
            la.Add(new ComparedObjectResult() { Type = "EntityID", A = entityA.EntityID });
            la.Add(new ComparedObjectResult() { Type = "CollectionMemberTable", A = entityA.CollectionMemberTable });
            la.Add(new ComparedObjectResult() { Type = "CollectionTable", A = entityA.CollectionTable });
            la.Add(new ComparedObjectResult() { Type = "EntityTable", A = entityA.EntityTable });
            la.Add(new ComparedObjectResult() { Type = "HierarchyParentTable", A = entityA.HierarchyParentTable });
            la.Add(new ComparedObjectResult() { Type = "HierarchyTable", A = entityA.HierarchyTable });
            la.Add(new ComparedObjectResult() { Type = "IsBase", A = entityA.IsBase });
            la.Add(new ComparedObjectResult() { Type = "IsFlat", A = entityA.IsFlat });
            la.Add(new ComparedObjectResult() { Type = "IsSystem", A = entityA.IsSystem });
            la.Add(new ComparedObjectResult() { Type = "SecurityTable", A = entityA.SecurityTable });
            la.Add(new ComparedObjectResult() { Type = "StagingBase", A = entityA.StagingBase });
            la.Add(new ComparedObjectResult() { Type = "CodeGenSeed", A = entityA.CodeGenSeed });

            return la;
        }
        #endregion
        #region Build Server Compare Attributes

        private static string GetRenamedEntity(ComparedObject co, CompareModel modelA, CompareModel modelB)
        {
            if (co.locationType == ObjectStatus.Rename)
            {
                var entityA = modelA.Entities[CompareEntity.getEntityKey(co.ObjectName)];
                foreach (var entityB in modelB.Entities)
                {
                    if (entityA.EntityMUID == entityB.Value.EntityMUID)
                    {
                        return entityB.Value.Name;
                    }
                }
            }
            return co.ObjectName;
        }

        private static string GetRenamedView(ComparedObject co, CompareModel modelA, CompareModel modelB)
        {

            if (co.locationType == ObjectStatus.Rename)
            {
                var viewA = modelA.Views[CompareView.getViewKey(co.ObjectName)];
                foreach (var viewB in modelB.Views)
                {
                    if (viewA.EntityMUID == viewB.Value.EntityMUID)
                    {
                        return viewB.Value.Name;
                    }
                }
            }
            return co.ObjectName;
        }

        public static List<ComparedAttributeGroups> buildServerSameDifferntRenameCompareAttributeGroups(ComparedObject co, CompareModel modelA, CompareModel modelB, CheckStates cStates)
        {
            string entityKeyNameA = CompareEntity.getEntityKey(co.ObjectName);
            string entityKeyNameB = CompareEntity.getEntityKey(GetRenamedEntity(co, modelA, modelB));

            if (modelA.Entities[entityKeyNameA].LComparedAttributeGroups == null)
            {

                var dcag = new Dictionary<string, ComparedAttributeGroups>();

                var en = modelA.Entities[entityKeyNameA];
                foreach (var ag in en.AttributeGroups)
                {

                    ComparedAttributeGroups cag = new ComparedAttributeGroups()
                    {
                        AttributeGroupA = ag.Value,
                        SortOrder = ag.Value.SortOrder,
                        comparedObject = co
                    };

                    if (modelB.Entities[entityKeyNameB].AttributeGroups.ContainsKey(ag.Key))
                    {
                        cag.AttributeGroupB = modelB.Entities[entityKeyNameB].AttributeGroups[ag.Key];
                        cag.Status = BusinessHelper.attributeGroupCompare(ag.Value,
                            modelB.Entities[entityKeyNameB].AttributeGroups[ag.Key], cStates);
                    }
                    else
                    {
                        //handle rename of attribute group
                        cag.Status = ObjectStatus.Missing;
                        foreach (var attributeGroupB in modelB.Entities[entityKeyNameB].AttributeGroups)
                        {
                            
                            if (ag.Value.MUID == attributeGroupB.Value.MUID)
                            {
                                cag.AttributeGroupB = attributeGroupB.Value;
                                cag.Status = BusinessHelper.attributeGroupCompare(ag.Value, attributeGroupB.Value, cStates);
                                break;
                            }
                        }

                    }
                    if (ObjectStatus.Same == cag.Status)
                    {
                        buildServerSameDifferntRenameCompareAttributeGroupDetails(cag, cStates);
                    }
                    dcag.Add(CompareAttributeGroup.getAttributeGroupKey(ag.Value.Name), cag);


                }

                //handle missing attribute group
                en = modelB.Entities[entityKeyNameB];
                foreach (var ag in en.AttributeGroups)
                {
                    if (!modelA.Entities[entityKeyNameA].AttributeGroups.ContainsKey(ag.Key))
                    {
                        //handle rename of attribute Group
                        bool hasBeenRenamed = false;
                        foreach (var attributeGroupA in modelA.Entities[entityKeyNameA].AttributeGroups)
                        {
                            if (ag.Value.MUID == attributeGroupA.Value.MUID)
                            {
                                hasBeenRenamed = true;
                                break;
                            }
                        }
                        if (!hasBeenRenamed)
                        {
                            ComparedAttributeGroups cag = new ComparedAttributeGroups()
                            {
                                //TODO: need to check this is working
                                AttributeGroupB = ag.Value,
                                SortOrder = ag.Value.SortOrder,
                                Status = ObjectStatus.Missing,
                                comparedObject = co
                            };
                            dcag.Add(CompareAttributeGroup.getAttributeGroupKey(ag.Value.Name), cag);
                        }
                    }
                }

                var lcag = dcag.Values.ToList();
                modelA.Entities[entityKeyNameA].LComparedAttributeGroups = lcag;
                modelB.Entities[entityKeyNameB].LComparedAttributeGroups = lcag;
            }

            var lcv = new ListCollectionView(modelA.Entities[entityKeyNameA].LComparedAttributeGroups);
            lcv.CustomSort = new ComparedBasedSorting();

            return modelA.Entities[entityKeyNameA].LComparedAttributeGroups;
        }
        public static List<ComparedAttributeGroups> buildServerBCompareAttributeGroups(ComparedObject co, CompareModel modelB)
        {
            string entityKeyName = CompareEntity.getEntityKey(co.ObjectName);
            if (modelB.Entities[entityKeyName].LComparedAttributeGroups == null)
            {
                var lcag = new List<ComparedAttributeGroups>();
                var en = modelB.Entities[entityKeyName];
                foreach (var ag in en.AttributeGroups)
                {
                    var cag = new ComparedAttributeGroups()
                    {
                        AttributeGroupB = ag.Value,
                        SortOrder = ag.Value.SortOrder,
                        comparedObject = co,
                        Status = ObjectStatus.Missing
                    };
                    lcag.Add(cag);
                }

                modelB.Entities[entityKeyName].LComparedAttributeGroups = lcag;
            }
            return modelB.Entities[entityKeyName].LComparedAttributeGroups;
        }
        public static List<ComparedAttributeGroups> buildServerACompareAttributeGroups(ComparedObject co, CompareModel modelA)
        {
            string entityKeyName = CompareEntity.getEntityKey(co.ObjectName);
            if (modelA.Entities[entityKeyName].LComparedAttributeGroups == null)
            {
                var lcag = new List<ComparedAttributeGroups>();
                var en = modelA.Entities[entityKeyName];
                foreach (var ag in en.AttributeGroups)
                {
                    var cag = new ComparedAttributeGroups()
                    {
                        AttributeGroupA = ag.Value,
                        SortOrder = ag.Value.SortOrder,
                        comparedObject = co,
                        Status = ObjectStatus.Missing
                    };
                    lcag.Add(cag);
                }
                modelA.Entities[entityKeyName].LComparedAttributeGroups = lcag;
            }

            return modelA.Entities[entityKeyName].LComparedAttributeGroups;
        }


        public static List<ComparedAttributes> buildServerSameDifferntRenameCompareAttributes(ComparedObject co, CompareModel modelA, CompareModel modelB, CheckStates cStates)
        {
            string entityKeyNameA = CompareEntity.getEntityKey(co.ObjectName);
            string entityKeyNameB = CompareEntity.getEntityKey(GetRenamedEntity(co, modelA, modelB));

            if (modelA.Entities[entityKeyNameA].LComparedAttributes == null)
            {

                var dca = new Dictionary<string, ComparedAttributes>();

                var en = modelA.Entities[entityKeyNameA];
                foreach (var a in en.Attributes)
                {
                    var ca = new ComparedAttributes();
                    ca = new ComparedAttributes()
                    {
                        AttributeA = a.Value,
                        MemberTypeA = a.Value.MemberType.ToString(),
                        SortOrder = a.Value.SortOrder,
                        comparedObject = co
                    };
                    if (modelB.Entities[entityKeyNameB].Attributes.ContainsKey(a.Key))
                    {
                        ca.AttributeB = modelB.Entities[entityKeyNameB].Attributes[a.Key];
                        ca.MemberTypeB = modelB.Entities[entityKeyNameB].Attributes[a.Key].MemberType.ToString();

                        ca.Status = BusinessHelper.attributeCompare(a.Value, modelB.Entities[entityKeyNameB].Attributes[a.Key], cStates);
                    }
                    else
                    {
                        //handle rename of attribute
                        foreach (var attributeB in modelB.Entities[entityKeyNameB].Attributes)
                        {
                            ca.Status = ObjectStatus.Missing;
                            if (a.Value.MUID == attributeB.Value.MUID)
                            {
                                ca.AttributeB = attributeB.Value;
                                ca.MemberTypeB = attributeB.Value.MemberType.ToString();
                                ca.Status = BusinessHelper.attributeCompare(a.Value, attributeB.Value, cStates);
                                break;
                            }
                        }

                    }
                    dca.Add(a.Value.Name + a.Value.MemberType.ToString(), ca);
                }

                //handle missing attribute
                en = modelB.Entities[entityKeyNameB];
                foreach (var a in en.Attributes)
                {
                    if (!modelA.Entities[entityKeyNameA].Attributes.ContainsKey(a.Key))
                    {
                        //handle rename of attribute
                        bool hasBeenRenamed = false;
                        foreach (var attributeA in modelA.Entities[entityKeyNameA].Attributes)
                        {
                            if (a.Value.MUID == attributeA.Value.MUID)
                            {
                                hasBeenRenamed = true;
                                break;
                            }
                        }
                        if (!hasBeenRenamed)
                        {
                            var ca = new ComparedAttributes();
                            ca = new ComparedAttributes()
                            {
                                //TODO: need to check this is working
                                AttributeB = a.Value,
                                MemberTypeB = a.Value.MemberType.ToString(),
                                SortOrder = a.Value.SortOrder,
                                Status = ObjectStatus.Missing,
                                comparedObject = co
                            };
                            dca.Add(a.Value.Name + a.Value.MemberType.ToString(), ca);
                        }
                    }
                }

                var lca = dca.Values.ToList();
                modelA.Entities[entityKeyNameA].LComparedAttributes = lca;
                modelB.Entities[entityKeyNameB].LComparedAttributes = lca;
            }

            var lcv = new ListCollectionView(modelA.Entities[entityKeyNameA].LComparedAttributes);
            lcv.CustomSort = new ComparedBasedSorting();

            return modelA.Entities[entityKeyNameA].LComparedAttributes;
        }
        public static List<ComparedAttributes> buildServerBCompareAttributes(ComparedObject co, CompareModel modelB)
        {
            string entityKeyName = CompareEntity.getEntityKey(co.ObjectName);
            if (modelB.Entities[entityKeyName].LComparedAttributes == null)
            {
                var lca = new List<ComparedAttributes>();
                var en = modelB.Entities[entityKeyName];
                foreach (var a in en.Attributes)
                {
                    var ca = new ComparedAttributes()
                    {
                        AttributeB = a.Value,
                        MemberTypeB = a.Value.MemberType.ToString(),
                        SortOrder = a.Value.SortOrder,
                        comparedObject = co,
                        Status = ObjectStatus.Missing
                    };
                    lca.Add(ca);
                }

                modelB.Entities[entityKeyName].LComparedAttributes = lca;
            }
            return modelB.Entities[entityKeyName].LComparedAttributes;
        }
        public static List<ComparedAttributes> buildServerACompareAttributes(ComparedObject co, CompareModel modelA)
        {
            string entityKeyName = CompareEntity.getEntityKey(co.ObjectName);
            if (modelA.Entities[entityKeyName].LComparedAttributes == null)
            {
                var lca = new List<ComparedAttributes>();
                var en = modelA.Entities[entityKeyName];
                foreach (var a in en.Attributes)
                {
                    var ca = new ComparedAttributes()
                    {
                        AttributeA = a.Value,
                        MemberTypeA = a.Value.MemberType.ToString(),
                        SortOrder = a.Value.SortOrder,
                        comparedObject = co,
                        Status = ObjectStatus.Missing
                    };
                    lca.Add(ca);
                }
                modelA.Entities[entityKeyName].LComparedAttributes = lca;
            }

            return modelA.Entities[entityKeyName].LComparedAttributes;
        }
        #endregion



        public static CompareAttribute getCompareAttribute(ComparedAttributes ca, ServerDirection server, CompareModel modelA, CompareModel modelB)
        {
            if (server == ServerDirection.ServerA)
            {
                if (modelA.Entities.ContainsKey(CompareEntity.getEntityKey(ca.comparedObject.ObjectName)) && ca.AttributeA != null && modelA.Entities[CompareEntity.getEntityKey(ca.comparedObject.ObjectName)].Attributes.ContainsKey(CompareAttribute.getAttributeKey(ca.AttributeA.Name, Convert.ToInt32(ca.MemberTypeA))))
                {
                    return modelA.Entities[CompareEntity.getEntityKey(ca.comparedObject.ObjectName)].Attributes[CompareAttribute.getAttributeKey(ca.AttributeA.Name, Convert.ToInt32(ca.MemberTypeA))];
                }
                else
                {
                    return null;
                }
            }
            else
            {
                if (modelB.Entities.ContainsKey(CompareEntity.getEntityKey(ca.comparedObject.ObjectName)) && ca.AttributeB != null && modelB.Entities[CompareEntity.getEntityKey(ca.comparedObject.ObjectName)].Attributes.ContainsKey(CompareAttribute.getAttributeKey(ca.AttributeB.Name, Convert.ToInt32(ca.MemberTypeB))))
                {
                    return modelB.Entities[CompareEntity.getEntityKey(ca.comparedObject.ObjectName)].Attributes[CompareAttribute.getAttributeKey(ca.AttributeB.Name, Convert.ToInt32(ca.MemberTypeB))];
                }
                else
                {
                    return null;
                }
            }
        }

        public static List<ComparedAttributeGroupDetails> buildServerSameDifferntRenameCompareAttributeGroupDetails(ComparedAttributeGroups cag, CheckStates cStates)
        {
            //rollup change to AttributeGroup
            ObjectStatus AttributeGroupStatus = ObjectStatus.Same;

            if (cag.LComparedAttributeGroupDetails == null)
            {
                var dcagd = new Dictionary<string, ComparedAttributeGroupDetails>();


                foreach (var agd in cag.AttributeGroupA.AttributeGroupDetails)
                {

                    ComparedAttributeGroupDetails cagd = new ComparedAttributeGroupDetails()
                    {
                        AttributeGroupDetailA = agd.Value,
                        SortOrder = agd.Value.SortOrder
                    };
                    if (cag.AttributeGroupB != null && cag.AttributeGroupB.AttributeGroupDetails.ContainsKey(agd.Key))
                    {
                        cagd.AttributeGroupDetailB = cag.AttributeGroupB.AttributeGroupDetails[agd.Key];
                        cagd.Status = BusinessHelper.attributeGroupDetailCompare(agd.Value, cag.AttributeGroupB.AttributeGroupDetails[agd.Key], cStates);
                    }
                    else
                    {
                        cagd.Status = ObjectStatus.Missing;
                        if (cag.AttributeGroupB != null)
                        {
                            //handle rename of attribute group detail
                            foreach (var agdB in cag.AttributeGroupB.AttributeGroupDetails)
                            {

                                if (agd.Value.MUID == agdB.Value.MUID)
                                {
                                    cagd.AttributeGroupDetailA = agdB.Value;
                                    cagd.Status = BusinessHelper.attributeGroupDetailCompare(agd.Value, agdB.Value,
                                        cStates);
                                    break;
                                }
                            }
                        }
                    }

                    if (cagd.Status != ObjectStatus.Same)
                    {
                        AttributeGroupStatus = ObjectStatus.Different;
                    }
                    dcagd.Add(CompareAttributeGroupDetail.getAttributeGroupDetailKey(agd.Value.AttributeGroup, agd.Value.Attribute), cagd);
                }

                //handle missing attribute group
                if (cag.AttributeGroupB != null)
                {
                    foreach (var agd in cag.AttributeGroupB.AttributeGroupDetails)
                    {
                        if (!cag.AttributeGroupA.AttributeGroupDetails.ContainsKey(agd.Key))
                        {
                            //handle rename of attribute Group Detail
                            bool hasBeenRenamed = false;
                            foreach (var attributeGroupDetailA in cag.AttributeGroupA.AttributeGroupDetails)
                            {
                                if (agd.Value.MUID == attributeGroupDetailA.Value.MUID)
                                {
                                    hasBeenRenamed = true;
                                    break;
                                }
                            }
                            if (!hasBeenRenamed)
                            {
                                ComparedAttributeGroupDetails cagd = new ComparedAttributeGroupDetails()
                                {
                                    //TODO: need to check this is working
                                    AttributeGroupDetailB = agd.Value,
                                    SortOrder = agd.Value.SortOrder,
                                    Status = ObjectStatus.Missing
                                    //,
                                    //AttributeGroup = agd.Value.AttributeGroup,
                                };
                                if (cagd.Status != ObjectStatus.Same)
                                {
                                    AttributeGroupStatus = ObjectStatus.Different;
                                }
                                dcagd.Add(
                                    CompareAttributeGroupDetail.getAttributeGroupDetailKey(agd.Value.AttributeGroup,
                                        agd.Value.Attribute), cagd);
                            }
                        }
                    }
                }

                var lcagd = dcagd.Values.ToList();
                cag.LComparedAttributeGroupDetails = lcagd;
            }
            else
            {
                foreach (var cagd in cag.LComparedAttributeGroupDetails)
                {
                    if (cagd.Status != ObjectStatus.Same)
                    {
                        AttributeGroupStatus = ObjectStatus.Different;
                        break;
                    }
                }

            }

            var lcv = new ListCollectionView(cag.LComparedAttributeGroupDetails);
            lcv.CustomSort = new ComparedBasedSorting();
            if (cag.Status == ObjectStatus.Same && AttributeGroupStatus != ObjectStatus.Same)
            {
                cag.Status = AttributeGroupStatus;
            }

            return cag.LComparedAttributeGroupDetails;
            
        }
        public static List<ComparedAttributeGroupDetails> buildServerBCompareAttributeGroupDetails(ComparedAttributeGroups cag)
        {
            if (cag.LComparedAttributeGroupDetails == null)
            {
                var lcagd = new List<ComparedAttributeGroupDetails>();

                foreach (var agd in cag.AttributeGroupB.AttributeGroupDetails)
                {
                    var cagd = new ComparedAttributeGroupDetails()
                    {
                        AttributeGroupDetailB = agd.Value,
                        SortOrder = agd.Value.SortOrder,
                        //AttributeGroup = agd.Value.AttributeGroup,
                        Status = ObjectStatus.Missing

                    };
                    lcagd.Add(cagd);
                }

                cag.LComparedAttributeGroupDetails = lcagd;
            }
            return cag.LComparedAttributeGroupDetails;
        }
        public static List<ComparedAttributeGroupDetails> buildServerACompareAttributeGroupDetails(ComparedAttributeGroups cag)
        {
            if (cag.LComparedAttributeGroupDetails == null)
            {
                var lcagd = new List<ComparedAttributeGroupDetails>();

                foreach (var agd in cag.AttributeGroupA.AttributeGroupDetails)
                {
                    var cagd = new ComparedAttributeGroupDetails()
                    {
                        AttributeGroupDetailA = agd.Value,
                        SortOrder = agd.Value.SortOrder,
                        //AttributeGroup = agd.Value.AttributeGroup,
                        Status = ObjectStatus.Missing

                    };
                    lcagd.Add(cagd);
                }

                cag.LComparedAttributeGroupDetails = lcagd;
            }

            return cag.LComparedAttributeGroupDetails;
        }


        public static List<ComparedObjectResult> PopulateComparedAttribute(ComparedAttributes ca, CompareModel modelA, CompareModel modelB)
        {
            var attA = modelA.Entities[CompareEntity.getEntityKey(ca.comparedObject.ObjectName)].Attributes[CompareAttribute.getAttributeKey(ca.AttributeA.Name, Convert.ToInt32(ca.MemberTypeA))];
            var attB = modelB.Entities[CompareEntity.getEntityKey(GetRenamedEntity(ca.comparedObject, modelA, modelB))].Attributes[CompareAttribute.getAttributeKey(ca.AttributeB.Name, Convert.ToInt32(ca.MemberTypeB))];
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", A = attA.Name, B = attB.Name });
            la.Add(new ComparedObjectResult() { Type = "SortOrder", A = attA.SortOrder, B = attB.SortOrder });
            la.Add(new ComparedObjectResult() { Type = "MemberType", A = attA.MemberType, B = attB.MemberType });
            la.Add(new ComparedObjectResult() { Type = "IsSystem", A = attA.IsSystem, B = attB.IsSystem });
            la.Add(new ComparedObjectResult() { Type = "MUID", A = attA.MUID, B = attB.MUID });
            la.Add(new ComparedObjectResult() { Type = "EntityID", A = attA.Entity.EntityID, B = attB.Entity.EntityID });
            la.Add(new ComparedObjectResult() { Type = "DisplayName", A = attA.DisplayName, B = attB.DisplayName });
            la.Add(new ComparedObjectResult() { Type = "TableColumn", A = attA.TableColumn, B = attB.TableColumn });
            la.Add(new ComparedObjectResult() { Type = "AttributeTypeID", A = attA.AttributeTypeID, B = attB.AttributeTypeID });
            la.Add(new ComparedObjectResult() { Type = "DataTypeID", A = attA.DataTypeID, B = attB.DataTypeID });
            la.Add(new ComparedObjectResult() { Type = "DataTypeInformation", A = attA.DataTypeInformation, B = attB.DataTypeInformation });
            la.Add(new ComparedObjectResult() { Type = "InputMaskID", A = attA.InputMaskID, B = attB.InputMaskID });
            la.Add(new ComparedObjectResult() { Type = "DisplayWidth", A = attA.DisplayWidth, B = attB.DisplayWidth });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityID", A = attA.DomainEntityID, B = attB.DomainEntityID });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityName", A = attA.DomainEntityName, B = attB.DomainEntityName });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityMUID", A = attA.DomainEntityMUID, B = attB.DomainEntityMUID });
            la.Add(new ComparedObjectResult() { Type = "ChangeTrackingGroup", A = attA.ChangeTrackingGroup, B = attB.ChangeTrackingGroup });
            la.Add(new ComparedObjectResult() { Type = "IsCode", A = attA.IsCode, B = attB.IsCode });
            la.Add(new ComparedObjectResult() { Type = "IsName", A = attA.IsName, B = attB.IsName });
            la.Add(new ComparedObjectResult() { Type = "IsReadOnly", A = attA.IsReadOnly, B = attB.IsReadOnly });
            la.Add(new ComparedObjectResult() { Type = "AttributeValidationID", A = attA.AttributeValidationID, B = attB.AttributeValidationID });
            la.Add(new ComparedObjectResult() { Type = "IsRequired", A = attA.IsRequired, B = attB.IsRequired });

            return la;
        }
        public static List<ComparedObjectResult> PopulateComparedAttributeA(ComparedAttributes ca, CompareModel modelA, CompareModel modelB)
        {
            var att = getCompareAttribute(ca, ServerDirection.ServerA, modelA, modelB);
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", A = att.Name });
            la.Add(new ComparedObjectResult() { Type = "SortOrder", A = att.SortOrder });
            la.Add(new ComparedObjectResult() { Type = "MemberType", A = att.MemberType });
            la.Add(new ComparedObjectResult() { Type = "IsSystem", A = att.IsSystem });
            la.Add(new ComparedObjectResult() { Type = "MUID", A = att.MUID });
            la.Add(new ComparedObjectResult() { Type = "EntityID", A = att.Entity.EntityID });
            la.Add(new ComparedObjectResult() { Type = "EntityName", A = att.Entity.Name });
            la.Add(new ComparedObjectResult() { Type = "DisplayName", A = att.DisplayName });
            la.Add(new ComparedObjectResult() { Type = "TableColumn", A = att.TableColumn });
            la.Add(new ComparedObjectResult() { Type = "AttributeTypeID", A = att.AttributeTypeID });
            la.Add(new ComparedObjectResult() { Type = "DataTypeID", A = att.DataTypeID });
            la.Add(new ComparedObjectResult() { Type = "DataTypeInformation", A = att.DataTypeInformation });
            la.Add(new ComparedObjectResult() { Type = "InputMaskID", A = att.InputMaskID });
            la.Add(new ComparedObjectResult() { Type = "DisplayWidth", A = att.DisplayWidth });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityID", A = att.DomainEntityID });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityName", A = att.DomainEntityName });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityMUID", A = att.DomainEntityMUID });
            la.Add(new ComparedObjectResult() { Type = "ChangeTrackingGroup", A = att.ChangeTrackingGroup });
            la.Add(new ComparedObjectResult() { Type = "IsCode", A = att.IsCode });
            la.Add(new ComparedObjectResult() { Type = "IsName", A = att.IsName });
            la.Add(new ComparedObjectResult() { Type = "IsReadOnly", A = att.IsReadOnly });
            la.Add(new ComparedObjectResult() { Type = "AttributeValidationID", A = att.AttributeValidationID });
            la.Add(new ComparedObjectResult() { Type = "IsRequired", A = att.IsRequired });

            return la;
        }
        public static List<ComparedObjectResult> PopulateComparedAttributeB(ComparedAttributes ca, CompareModel modelA, CompareModel modelB)
        {
            var att = getCompareAttribute(ca, ServerDirection.ServerB, modelA, modelB);
            var la = new List<ComparedObjectResult>();
            la.Add(new ComparedObjectResult() { Type = "Name", B = att.Name });
            la.Add(new ComparedObjectResult() { Type = "SortOrder", B = att.SortOrder });
            la.Add(new ComparedObjectResult() { Type = "MemberType", B = att.MemberType });
            la.Add(new ComparedObjectResult() { Type = "IsSystem", B = att.IsSystem });
            la.Add(new ComparedObjectResult() { Type = "MUID", B = att.MUID });
            la.Add(new ComparedObjectResult() { Type = "EntityID", B = att.Entity.EntityID });
            la.Add(new ComparedObjectResult() { Type = "EntityName", B = att.Entity.Name });
            la.Add(new ComparedObjectResult() { Type = "DisplayName", B = att.DisplayName });
            la.Add(new ComparedObjectResult() { Type = "TableColumn", B = att.TableColumn });
            la.Add(new ComparedObjectResult() { Type = "AttributeTypeID", B = att.AttributeTypeID });
            la.Add(new ComparedObjectResult() { Type = "DataTypeID", B = att.DataTypeID });
            la.Add(new ComparedObjectResult() { Type = "DataTypeInformation", B = att.DataTypeInformation });
            la.Add(new ComparedObjectResult() { Type = "InputMaskID", B = att.InputMaskID });
            la.Add(new ComparedObjectResult() { Type = "DisplayWidth", B = att.DisplayWidth });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityID", B = att.DomainEntityID });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityName", B = att.DomainEntityName });
            la.Add(new ComparedObjectResult() { Type = "DomainEntityMUID", B = att.DomainEntityMUID });
            la.Add(new ComparedObjectResult() { Type = "ChangeTrackingGroup", B = att.ChangeTrackingGroup });
            la.Add(new ComparedObjectResult() { Type = "IsCode", B = att.IsCode });
            la.Add(new ComparedObjectResult() { Type = "IsName", B = att.IsName });
            la.Add(new ComparedObjectResult() { Type = "IsReadOnly", B = att.IsReadOnly });
            la.Add(new ComparedObjectResult() { Type = "AttributeValidationID", B = att.AttributeValidationID });
            la.Add(new ComparedObjectResult() { Type = "IsRequired", B = att.IsRequired });

            return la;
        }

        private static CompareAttributeGroup getCompareAttributeGroup(ComparedAttributeGroups cag, ServerDirection server, CompareModel modelA, CompareModel modelB)
        {
            if (server == ServerDirection.ServerA)
            {
                if (modelA.Entities.ContainsKey(CompareEntity.getEntityKey(cag.comparedObject.ObjectName)) && cag.AttributeGroupA != null && modelA.Entities[CompareEntity.getEntityKey(cag.comparedObject.ObjectName)].AttributeGroups.ContainsKey(CompareAttributeGroup.getAttributeGroupKey(cag.AttributeGroupA.Name)))
                {
                    return modelA.Entities[CompareEntity.getEntityKey(cag.comparedObject.ObjectName)].AttributeGroups[CompareAttributeGroup.getAttributeGroupKey(cag.AttributeGroupA.Name)];
                }
                else
                {
                    return null;
                }
            }
            else
            {
                if (modelB.Entities.ContainsKey(CompareEntity.getEntityKey(cag.comparedObject.ObjectName)) && cag.AttributeGroupB != null && modelB.Entities[CompareEntity.getEntityKey(cag.comparedObject.ObjectName)].AttributeGroups.ContainsKey(CompareAttributeGroup.getAttributeGroupKey(cag.AttributeGroupB.Name)))
                {
                    return modelB.Entities[CompareEntity.getEntityKey(cag.comparedObject.ObjectName)].AttributeGroups[CompareAttributeGroup.getAttributeGroupKey(cag.AttributeGroupB.Name)];
                }
                else
                {
                    return null;
                }
            }
        }

        public static List<ComparedObjectResult> PopulateComparedAttributeGroup(ComparedAttributeGroups cag, CompareModel modelA, CompareModel modelB)
        {
            var attGroupA = modelA.Entities[CompareEntity.getEntityKey(cag.comparedObject.ObjectName)].AttributeGroups[CompareAttributeGroup.getAttributeGroupKey(cag.AttributeGroupA.Name)];
            var attGroupB = modelB.Entities[CompareEntity.getEntityKey(GetRenamedEntity(cag.comparedObject, modelA, modelB))].AttributeGroups[CompareAttributeGroup.getAttributeGroupKey(cag.AttributeGroupB.Name)];
            var lag = new List<ComparedObjectResult>();
            lag.Add(new ComparedObjectResult() { Type = "Name", A = attGroupA.Name, B = attGroupB.Name });
            lag.Add(new ComparedObjectResult() { Type = "MUID", A = attGroupA.MUID, B = attGroupB.MUID });
            lag.Add(new ComparedObjectResult() { Type = "SortOrder", A = attGroupA.SortOrder, B = attGroupB.SortOrder });


            return lag;
        }
        public static List<ComparedObjectResult> PopulateComparedAttributeGroupA(ComparedAttributeGroups cag, CompareModel modelA, CompareModel modelB)
        {
            var attGroup = getCompareAttributeGroup(cag, ServerDirection.ServerA, modelA, modelB);
            var lag = new List<ComparedObjectResult>();
            lag.Add(new ComparedObjectResult() { Type = "Name", A = attGroup.Name });
            lag.Add(new ComparedObjectResult() { Type = "MUID", A = attGroup.MUID });
            lag.Add(new ComparedObjectResult() { Type = "SortOrder", A = attGroup.SortOrder });


            return lag;
        }
        public static List<ComparedObjectResult> PopulateComparedAttributeGroupB(ComparedAttributeGroups cag, CompareModel modelA, CompareModel modelB)
        {
            var attGroup = getCompareAttributeGroup(cag, ServerDirection.ServerB, modelA, modelB);
            var lag = new List<ComparedObjectResult>();

            lag.Add(new ComparedObjectResult() { Type = "Name", B = attGroup.Name });
            lag.Add(new ComparedObjectResult() { Type = "MUID", B = attGroup.MUID });
            lag.Add(new ComparedObjectResult() { Type = "SortOrder", B = attGroup.SortOrder });

            return lag;
        }

        private static CompareAttributeGroupDetail getCompareAttributeGroupDetail(ComparedAttributeGroupDetails cagd, ServerDirection server)
        {
            if (server == ServerDirection.ServerA)
            {
                return cagd.AttributeGroupDetailA;
            }
            else
            {
                return cagd.AttributeGroupDetailB;
            }
        }

        #region deploy schema compare
        public static void getSelectedEntities(DeploymentBuilder db, CompareModel modelA, CompareModel modelB, ServerDirection sDirection, CheckStates cStates, List<ComparedObject> Items)
        {
            //if (dgDataMdsObject.Items.SourceCollection != null)
            //{
                //foreach (object r in dgDataMdsObject.Items.SourceCollection)
            foreach (ComparedObject co in Items)
                {
            //        if (r.GetType().FullName == Constants.MDSADMINISTRATION_COMPAREDOBJECT)
            //        {
            //            ComparedObject co = (ComparedObject)r;
                        if (co.Checked && co.ObjectType == Constants.OBJECT_TYPE_ENTITY)
                        {
                            CompareEntity ce = null;
                            CompareEntity ceDestination = null;
                            if (sDirection == ServerDirection.ServerA)
                            {
                                ce = getCompareEntity(co, ServerDirection.ServerB, modelA, modelB);
                                ceDestination = getCompareEntity(co, ServerDirection.ServerA, modelA, modelB);
                            }
                            else
                            {
                                ce = getCompareEntity(co, ServerDirection.ServerA, modelA, modelB);
                                ceDestination = getCompareEntity(co, ServerDirection.ServerB, modelA, modelB);
                            }


                            switch (co.locationType)
                            {
                                case ObjectStatus.ServerA:
                                    {
                                        if (sDirection == ServerDirection.ServerB)
                                        {
                                            db.LActionEntities.Add(new ActionEntity() { ce = ce, status = ObjectStatus.Missing, buildStaging = true, syncGuid = (!cStates.EntityMUID) });
                                        }
                                        else
                                        {
                                            db.LActionEntities.Add(new ActionEntity() { ceDestination = ceDestination, status = ObjectStatus.Delete, buildStaging = false, syncGuid = (!cStates.EntityMUID) });
                                        }
                                    }
                                    break;
                                case ObjectStatus.ServerB:
                                    {
                                        if (sDirection == ServerDirection.ServerA)
                                        {
                                            db.LActionEntities.Add(new ActionEntity() { ce = ce, status = ObjectStatus.Missing, buildStaging = true, syncGuid = (!cStates.EntityMUID) });
                                        }
                                        else
                                        {
                                            db.LActionEntities.Add(new ActionEntity() { ceDestination = ceDestination, status = ObjectStatus.Delete, buildStaging = false, syncGuid = (!cStates.EntityMUID) });
                                        }
                                    }
                                    break;
                                case ObjectStatus.Different:
                                    {
                                        db.LActionEntities.Add(new ActionEntity() { ce = ce, ceDestination = ceDestination, status = co.locationType, buildStaging = (!cStates.StagingTable), syncGuid = (!cStates.EntityMUID) });
                                    }
                                    break;
                                case ObjectStatus.Rename:
                                    {
                                        db.LActionEntities.Add(new ActionEntity() { ce = ce, ceDestination = ceDestination, status = co.locationType, buildStaging = (!cStates.StagingTable), syncGuid = (!cStates.EntityMUID) });
                                    }
                                    break;
                            }
                        }
                    }
              //  }
            //}
        }
        
        private static CompareEntity getCompareEntity(ComparedObject co, ServerDirection server, CompareModel modelA, CompareModel modelB)
        {
            if (server == ServerDirection.ServerA)
            {
                if (modelA.Entities.ContainsKey(CompareEntity.getEntityKey(co.ObjectName)))
                {
                    return modelA.Entities[CompareEntity.getEntityKey(co.ObjectName)];
                }
                else
                {
                    return null;
                }
            }
            else
            {
                if (modelB.Entities.ContainsKey(CompareEntity.getEntityKey(GetRenamedEntity(co, modelA, modelB))))
                {
                    return modelB.Entities[CompareEntity.getEntityKey(GetRenamedEntity(co, modelA, modelB))];
                }
                else
                {
                    return null;
                }
            }
        }

        public static void getSelectedViews(DeploymentBuilder db, CompareModel modelA, CompareModel modelB, ServerDirection sDirection, List<ComparedObject> Items)
        {
            //if (dgDataMdsObject.Items.SourceCollection != null)
            //{
            //    foreach (object r in dgDataMdsObject.Items.SourceCollection)
            //    {

            foreach (ComparedObject co in Items)
            {
                //if (r.GetType().FullName == Constants.MDSADMINISTRATION_COMPAREDOBJECT)
                //{
                //    ComparedObject co = (ComparedObject)r;
                if (co.Checked && co.ObjectType == "View")
                {
                    CompareView cv = null;
                    CompareView cvDestination = null;
                    if (sDirection == ServerDirection.ServerA)
                    {
                        cv = getCompareView(co, ServerDirection.ServerB, modelA, modelB);
                        cvDestination = getCompareView(co, ServerDirection.ServerA, modelA, modelB);
                    }
                    else
                    {
                        cv = getCompareView(co, ServerDirection.ServerA, modelA, modelB);
                        cvDestination = getCompareView(co, ServerDirection.ServerB, modelA, modelB);
                    }

                    switch (co.locationType)
                    {
                        case ObjectStatus.ServerA:
                            {
                                if (sDirection == ServerDirection.ServerB)
                                {
                                    db.LActionViews.Add(new ActionView() { cv = cv, status = ObjectStatus.Missing });
                                }
                                else
                                {
                                    db.LActionViews.Add(new ActionView() { cv = cv, status = ObjectStatus.Delete });
                                }
                            }
                            break;
                        case ObjectStatus.ServerB:
                            {
                                if (sDirection == ServerDirection.ServerA)
                                {
                                    db.LActionViews.Add(new ActionView() { cv = cv, status = ObjectStatus.Missing });
                                }
                                else
                                {
                                    db.LActionViews.Add(new ActionView() { cv = cv, status = ObjectStatus.Delete });
                                }
                            }
                            break;
                        case ObjectStatus.Different:
                            {
                                db.LActionViews.Add(new ActionView() { cv = cv, status = co.locationType });
                            }
                            break;
                        case ObjectStatus.Rename:
                            {
                                db.LActionViews.Add(new ActionView() { cv = cv, cvDestination = cvDestination, status = co.locationType });
                            }
                            break;

                    }
                }
                //      }
            }
            //}
        }
        private static CompareView getCompareView(ComparedObject co, ServerDirection server, CompareModel modelA, CompareModel modelB)
        {
            if (server == ServerDirection.ServerA)
            {
                if (modelA.Views.ContainsKey(CompareView.getViewKey(co.ObjectName)))
                {
                    return modelA.Views[CompareView.getViewKey(co.ObjectName)];
                }
                else
                {
                    return null;
                }
            }
            else
            {
                if (modelB.Views.ContainsKey(CompareView.getViewKey(GetRenamedView(co, modelA, modelB))))
                {
                    return modelB.Views[CompareView.getViewKey(GetRenamedView(co, modelA, modelB))];
                }
                else
                {
                    return null;
                }
            }
        }
        public static void getSelectedAttributes(DeploymentBuilder db, CompareModel modelA, CompareModel modelB, ServerDirection sDirection, CheckStates cStates)
        {
            Dictionary<string, CompareEntity> Entities;
            if (sDirection == ServerDirection.ServerA)
            {
                Entities = modelA.Entities;
            }
            else
            {
                Entities = modelB.Entities;
            }
            foreach (var e in Entities)
            {
                if (e.Value.LComparedAttributes != null)
                {
                    foreach (object r in e.Value.LComparedAttributes)
                    {
                        if (r.GetType().FullName == Constants.MDSADMINISTRATION_COMPAREDATTRIBUTES)
                        {
                            ComparedAttributes cas = (ComparedAttributes)r;
                            if (cas.Checked)
                            {
                                switch (cas.Status)
                                {
                                    case ObjectStatus.Missing:
                                        {
                                            CompareAttribute ca = null;
                                            if (sDirection == ServerDirection.ServerA)
                                            {
                                                ca = getCompareAttribute(cas, ServerDirection.ServerB, modelA, modelB);
                                            }
                                            else
                                            {
                                                ca = getCompareAttribute(cas, ServerDirection.ServerA, modelA, modelB);
                                            }

                                            db.LActionAttributes.Add(new ActionAttribute() { ca = ca, status = cas.Status, syncGuid = (!cStates.AttributeMUID) });
                                        }
                                        break;
                                    case ObjectStatus.Delete:
                                    case ObjectStatus.Different:
                                    case ObjectStatus.Rename:
                                        {
                                            CompareAttribute ca = null;
                                            CompareAttribute caDestination = null;
                                            if (sDirection == ServerDirection.ServerA)
                                            {
                                                ca = getCompareAttribute(cas, ServerDirection.ServerB, modelA, modelB);
                                                caDestination = getCompareAttribute(cas, ServerDirection.ServerA, modelA, modelB);
                                            }
                                            else
                                            {
                                                ca = getCompareAttribute(cas, ServerDirection.ServerA, modelA, modelB);
                                                caDestination = getCompareAttribute(cas, ServerDirection.ServerB, modelA, modelB);
                                            }
                                            db.LActionAttributes.Add(new ActionAttribute()
                                            {
                                                ca = ca,
                                                caDestination = caDestination,
                                                status = cas.Status,
                                                syncGuid = (!cStates.AttributeMUID)
                                            });
                                        }
                                        break;

                                    default:
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }

        public static void getSelectedAttributeGroups(DeploymentBuilder db, CompareModel modelA, CompareModel modelB, ServerDirection sDirection, CheckStates cStates)
        {
            Dictionary<string, CompareEntity> Entities;
            if (sDirection == ServerDirection.ServerA)
            {
                Entities = modelA.Entities;
            }
            else
            {
                Entities = modelB.Entities;
            }
            foreach (var e in Entities)
            {
                if (e.Value.LComparedAttributeGroups != null)
                {
                    foreach (ComparedAttributeGroups cag in e.Value.LComparedAttributeGroups)
                    {
                        if (cag.Checked)
                        {
                            switch (cag.Status)
                            {
                                case ObjectStatus.Missing:
                                    {
                                        CompareAttributeGroup ag = null;
                                        if (sDirection == ServerDirection.ServerA)
                                        {
                                            ag = getCompareAttributeGroup(cag, ServerDirection.ServerB, modelA, modelB);
                                        }
                                        else
                                        {
                                            ag = getCompareAttributeGroup(cag, ServerDirection.ServerA, modelA, modelB);
                                        }
                                        if (ag != null)
                                        {
                                            db.LActionAttributeGroups.Add(new ActionAttributeGroup()
                                            {
                                                cag = ag,
                                                status = cag.Status,
                                                syncGuid = (!cStates.AttributeGroupMUID)
                                            });
                                        }
                                    }
                                    break;
                                case ObjectStatus.Delete:
                                case ObjectStatus.Different:
                                case ObjectStatus.Rename:
                                    {
                                        CompareAttributeGroup ag = null;
                                        CompareAttributeGroup agDestination = null;
                                        if (sDirection == ServerDirection.ServerA)
                                        {
                                            ag = getCompareAttributeGroup(cag, ServerDirection.ServerB, modelA, modelB);
                                            agDestination = getCompareAttributeGroup(cag, ServerDirection.ServerA, modelA, modelB);
                                        }
                                        else
                                        {
                                            ag = getCompareAttributeGroup(cag, ServerDirection.ServerA, modelA, modelB);
                                            agDestination = getCompareAttributeGroup(cag, ServerDirection.ServerB, modelA, modelB);
                                        }
                                        db.LActionAttributeGroups.Add(new ActionAttributeGroup()
                                        {
                                            cag = ag,
                                            cagDestination = agDestination,
                                            status = cag.Status,
                                            syncGuid = (!cStates.AttributeGroupMUID)
                                        });
                                    }
                                    break;
                            }
                        }

                    }
                }
            }
        }
        public static void getSelectedAttributeGroupDetails(DeploymentBuilder db, CompareModel modelA, CompareModel modelB, ServerDirection sDirection, CheckStates cStates)
        {
            Dictionary<string, CompareEntity> Entities;
            if (sDirection == ServerDirection.ServerA)
            {
                Entities = modelA.Entities;
            }
            else
            {
                Entities = modelB.Entities;
            }
            foreach (var e in Entities)
            {
                if (e.Value.LComparedAttributeGroups != null)
                {
                    foreach (ComparedAttributeGroups cag in e.Value.LComparedAttributeGroups)
                    {
                        if (cag.LComparedAttributeGroupDetails == null)
                        {
                            continue;
                        }
                        foreach (var cagd in cag.LComparedAttributeGroupDetails)
                        {
                            if (cagd.Checked)
                            {
                                switch (cagd.Status)
                                {
                                    case ObjectStatus.Missing:
                                        {
                                            CompareAttributeGroupDetail agd = null;
                                            if (sDirection == ServerDirection.ServerA)
                                            {
                                                agd = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerB);
                                            }
                                            else
                                            {
                                                agd = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerA);
                                            }
                                            if (agd != null)
                                            {
                                                db.LActionAttributeGroupDetails.Add(new ActionAttributeGroupDetail()
                                                {
                                                    cagd = agd,
                                                    status = cagd.Status,
                                                    syncGuid = (!cStates.AttributeGroupMUID)
                                                });
                                            }
                                        }
                                        break;
                                    case ObjectStatus.Delete:
                                    case ObjectStatus.Different:
                                    case ObjectStatus.Rename: //Should never occur
                                        {
                                            CompareAttributeGroupDetail agd = null;
                                            CompareAttributeGroupDetail agdDestination = null;
                                            if (sDirection == ServerDirection.ServerA)
                                            {
                                                agd = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerB);
                                                agdDestination = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerA);
                                            }
                                            else
                                            {
                                                agd = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerA);
                                                agdDestination = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerB);
                                            }
                                            db.LActionAttributeGroupDetails.Add(new ActionAttributeGroupDetail()
                                            {
                                                cagd = agd,
                                                cagdDestination = agdDestination,
                                                status = cagd.Status,
                                                syncGuid = (!cStates.AttributeGroupMUID)
                                            });
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }
        #endregion
        public static List<ComparedObjectResult> PopulateComparedAttributeGroupDetail(ComparedAttributeGroupDetails cagd)
        {

            var attGroupDetailA = cagd.AttributeGroupDetailA;
            var attGroupDetailB = cagd.AttributeGroupDetailB;
            var lagd = new List<ComparedObjectResult>();
            lagd.Add(new ComparedObjectResult() { Type = "Name", A = attGroupDetailA.Name, B = attGroupDetailB.Name });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeName", A = attGroupDetailA.Attribute.Name, B = attGroupDetailB.Attribute.Name });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeGroupName", A = attGroupDetailA.AttributeGroup.Name, B = attGroupDetailB.AttributeGroup.Name });
            lagd.Add(new ComparedObjectResult() { Type = "MUID", A = attGroupDetailA.MUID, B = attGroupDetailB.MUID });
            lagd.Add(new ComparedObjectResult() { Type = "SortOrder", A = attGroupDetailA.SortOrder, B = attGroupDetailB.SortOrder });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeID", A = attGroupDetailA.AttributeID, B = attGroupDetailB.AttributeID });

            return lagd;
        }
        public static List<ComparedObjectResult> PopulateComparedAttributeGroupDetailA(ComparedAttributeGroupDetails cagd)
        {
            var attGroupDetail = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerA);
            var lagd = new List<ComparedObjectResult>();

            lagd.Add(new ComparedObjectResult() { Type = "Name", A = attGroupDetail.Name });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeName", A = attGroupDetail.Attribute.Name });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeGroupName", A = attGroupDetail.AttributeGroup.Name });
            lagd.Add(new ComparedObjectResult() { Type = "MUID", A = attGroupDetail.MUID });
            lagd.Add(new ComparedObjectResult() { Type = "SortOrder", A = attGroupDetail.SortOrder });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeID", A = attGroupDetail.AttributeID });

            return lagd;
        }
        public static List<ComparedObjectResult> PopulateComparedAttributeGroupDetailB(ComparedAttributeGroupDetails cagd)
        {
            var attGroupDetail = getCompareAttributeGroupDetail(cagd, ServerDirection.ServerB);
            var lagd = new List<ComparedObjectResult>();
            lagd.Add(new ComparedObjectResult() { Type = "Name", B = attGroupDetail.Name });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeName", B = attGroupDetail.Attribute.Name });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeGroupName", B = attGroupDetail.AttributeGroup.Name });
            lagd.Add(new ComparedObjectResult() { Type = "MUID", B = attGroupDetail.MUID });
            lagd.Add(new ComparedObjectResult() { Type = "SortOrder", B = attGroupDetail.SortOrder });
            lagd.Add(new ComparedObjectResult() { Type = "AttributeID", B = attGroupDetail.AttributeID });

            return lagd;
        }


    }
}
